import cv2 as cv
import numpy as np
from utils.transition import qsqLinear, sqLinear, linear, linearFloat
from utils.methods import rotateImgCrop
from PIL import Image

class GenerateV():

  def __init__(self, outputPath, size, fps=24):
    fourcc = cv.VideoWriter_fourcc(*'MP4V')
    self.__wait = int(1000 / fps)
    # self.__vw = cv.VideoWriter(outputPath, fourcc, fps, size)

  # 纵向中心展开
  def unfoldColumnFromCenter(self, bg, front):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    screenH = 10
    frameCount1 = 32
    waitFrame = 40

    steps = qsqLinear(frameCount1, 0, bh)
    screen = np.ones((int(screenH/2), bw, 3), dtype=np.uint8) * 240
    a1Res = []
    for i, item in enumerate(steps):
      if i == 0:
        screen1 = np.ones((screenH, bw, 3), dtype=np.uint8) * 240
        bg[int((bh-screenH)/2):int((bh-screenH)/2+screenH), :] = screen1
        cv.imshow('frame', bg)
        # self.__vw.write(bg)
        cv.waitKey(self.__wait)
        continue

      ty = int((bh-item)/2)
      by = int((bh-item)/2 + item)
      fig = front[int((bh-item)/2):int(((bh-item)/2+item)), :]
      if int(by-ty) <= bh-screenH:
        bg[int(ty-screenH/2):ty, :] = screen
        bg[by:int(by+screenH/2), :] = screen
      else:
        wscreen = np.ones((bh, bw, 3), dtype=np.uint8) * 240
        bg = wscreen
      fig = cv.resize(fig, (bw, (by-ty)))
      bg[ty:by, :] = fig
      a1Res = bg
      cv.imshow('frame', bg)
      # self.__vw.write(bg)
      cv.waitKey(self.__wait)

    scales = sqLinear(8, 1, 1.15)
    for item in scales:
      scaleFront = cv.resize(a1Res, (int(bw*item), int(bh*item)))
      fh, fw = scaleFront.shape[:2]
      scaleFront = scaleFront[int((fh-bh)/2):int((fh-bh)/2+bh), int((fw-bw)/2):int((fw-bw)/2+bw)]
      scaleFront = cv.resize(scaleFront, (bw, bh))
      front = scaleFront
      cv.imshow('frame', front)
      # self.__vw.write(front)
      cv.waitKey(self.__wait)
 
    self.__waitTime(front, waitFrame=waitFrame)   

  # 横向中心展开
  def unfoldRowFromCenter(self, bg, front):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    screenW = 10
    frameCount1 = 32
    waitFrame = 40
    
    steps = qsqLinear(frameCount1, 0, bw)
    screen = np.ones((bh, int(screenW/2), 3), dtype=np.uint8) * 240
    a1Res = []
    for i, item in enumerate(steps):
      if i == 0:
        screen1 = np.ones((bh, screenW, 3), dtype=np.uint8) * 240
        bg[:, int((bw-screenW)/2):int((bw-screenW)/2+screenW)] = screen1
        cv.imshow('frame', bg)
        # self.__vw.write(bg)
        cv.waitKey(self.__wait)
        continue

      tlx = int((bw-item)/2)
      trx = int((bw-item)/2 + item)
      fig = front[: , int((bw-item)/2):int(((bw-item)/2+item))]
      if int(trx-tlx) <= bw-screenW:
        bg[:, int(tlx-screenW/2):tlx] = screen
        bg[:, trx:int(trx+screenW/2)] = screen
      else:
        wscreen = np.ones((bh, bw, 3), dtype=np.uint8) * 240
        bg = wscreen
      fig = cv.resize(fig, ((trx-tlx), bh))
      bg[:, tlx:trx] = fig
      a1Res = bg
      cv.imshow('frame', bg)
      # self.__vw.write(bg)
      cv.waitKey(self.__wait)

    self.__waitTime(front, waitFrame=waitFrame)  

  # 横向左侧展开
  def unfoldRowFromLeft(self, bg, front):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    screenW = 5
    frameCount1 = 36
    waitFrame = 40
    
    steps = qsqLinear(frameCount1, 0, bw, areaRate=[0.5, 0.08, 0.42], frameRate=[0.3, 0.25, 0.18])
    screen = np.ones((bh, screenW, 3), dtype=np.uint8) * 240
    for i, item in enumerate(steps):
      if i == 0:
        cv.imshow('frame', bg)
        # self.__vw.write(bg)
        cv.waitKey(self.__wait)
        continue

      tlx = 0
      trx = int(item)
      fig = front[: , (nw-item):nw]
      if bw-item >= screenW:
        bg[:, item:int(item+screenW)] = screen
      else:
        wscreen = np.ones((bh, bw, 3), dtype=np.uint8) * 240
        bg = wscreen
      fig = cv.resize(fig, ((trx-tlx), bh))
      bg[:, tlx:trx] = fig
      cv.imshow('frame', bg)
      # self.__vw.write(bg)
      cv.waitKey(self.__wait)

    self.__waitTime(front, waitFrame=waitFrame)  

  # 横向右侧展开
  def unfoldRowFromRight(self, bg, front):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    screenW = 5
    frameCount1 = 32
    waitFrame = 40
    
    steps = qsqLinear(frameCount1, 0, bw, areaRate=[0.5, 0.08, 0.42], frameRate=[0.3, 0.25, 0.21])
    screen = np.ones((bh, screenW, 3), dtype=np.uint8) * 240
    for i, item in enumerate(steps):
      if i == 0:
        cv.imshow('frame', bg)
        # self.__vw.write(bg)
        cv.waitKey(self.__wait)
        continue

      tlx = int(bw-item)
      trx = bw
      fig = front[: , 0:item]
      if bw-item >= screenW:
        bg[:, int(bw-item-screenW):int(bw-item)] = screen
      else:
        wscreen = np.ones((bh, bw, 3), dtype=np.uint8) * 240
        bg = wscreen
      fig = cv.resize(fig, ((trx-tlx), bh))
      bg[:, tlx:trx] = fig
      cv.imshow('frame', bg)

      # self.__vw.write(bg)
      cv.waitKey(self.__wait)

    self.__waitTime(front, waitFrame=waitFrame)  

  # 纵向顶部展开
  def unfoldColumnFromTop(self, bg, front):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    screenH = 5
    frameCount1 = 32
    waitFrame = 40
    
    steps = qsqLinear(frameCount1, 0, bh, areaRate=[0.5, 0.08, 0.42], frameRate=[0.26, 0.25, 0.18])
    screen = np.ones((screenH, bw, 3), dtype=np.uint8) * 240
    for i, item in enumerate(steps):
      if i == 0:
        cv.imshow('frame', bg)
        # self.__vw.write(bg)
        cv.waitKey(self.__wait)
        continue

      ty = 0
      by = int(item)
      fig = front[int(nh-item):nh , :]
      if bh-item >= screenH:
        bg[item:(item+screenH), :] = screen
      else:
        wscreen = np.ones((bh, bw, 3), dtype=np.uint8) * 240
        bg = wscreen
      fig = cv.resize(fig, (bw, (by-ty)))
      bg[ty:by, :] = fig
      cv.imshow('frame', bg)
      # self.__vw.write(bg)
      cv.waitKey(self.__wait)

    self.__waitTime(front, waitFrame=waitFrame)
    
  # 纵向底部展开
  def unfoldColumnFromBottom(self, bg, front):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    screenH = 5
    frameCount1 = 32
    waitFrame = 40
    
    steps = qsqLinear(frameCount1, 0, bh, areaRate=[0.5, 0.08, 0.42], frameRate=[0.26, 0.25, 0.18])
    screen = np.ones((screenH, bw, 3), dtype=np.uint8) * 240
    for i, item in enumerate(steps):
      if i == 0:
        cv.imshow('frame', bg)
        # self.__vw.write(bg)
        cv.waitKey(self.__wait)
        continue

      ty = bh-item
      by = bh
      fig = front[0:item , :]
      if bh-item >= screenH:
        bg[(bh-item-screenH):(bh-item), :] = screen
      else:
        wscreen = np.ones((bh, bw, 3), dtype=np.uint8) * 240
        bg = wscreen
      fig = cv.resize(fig, (bw, (by-ty)))
      bg[ty:by, :] = fig
      cv.imshow('frame', bg)
      # self.__vw.write(bg)
      cv.waitKey(self.__wait)

    self.__waitTime(front, waitFrame=waitFrame)

  # 上下两侧切片拼合
  def pieceColumnFromSides(self, bg, front, piece=5):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    screenH = 5
    frameCount1 = 18
    waitFrame = 40
    
    steps = linear(frameCount1, 0, bh)
    sw = int(bw / piece)

    for i, item in enumerate(steps):
      if i == 0:
        cv.imshow('frame', bg)
        # self.__vw.write(bg)
        cv.waitKey(self.__wait)
        continue

      for b in range(0, piece):
        if b % 2 == 0: 
          # 底部向上的块
          bty = bh - item
          bby = bh
          bfig = front[0:item , b*sw:(b+1)*sw]
          bfig = cv.resize(bfig, (sw, (bby-bty)))
          bg[bty:bby, b*sw:(b+1)*sw] = bfig
          cv.imshow('frame', bg)
          # self.__vw.write(bg)
        else:  
          # 顶部向下的块
          tty = 0
          tby = item
          fig = front[int(nh-item):nh , b*sw:(b+1)*sw]
          fig = cv.resize(fig, (sw, (tby-tty)))
          bg[tty:tby, b*sw:(b+1)*sw] = fig
          cv.imshow('frame', bg)
          # self.__vw.write(bg)
          # cv.waitKey(self.__wait)
        
      cv.waitKey(self.__wait)    

    self.__waitTime(front, waitFrame=waitFrame)
  
  def opacityTransform(self, bg, front):
    bh, bw = bg.shape[:2]
    nh, nw = front.shape[:2]
    if bh != nh and bw != nw:
      raise ValueError('图片尺寸不符')

    frameCount1 = 42
    waitFrame = 40  
    steps = linearFloat(frameCount1, 0, 1)
    print(steps)
    for i, item in enumerate(steps):
      alpha = item
      beta = 1 - alpha
      gamma = 0
      res = cv.addWeighted(front, alpha, bg, beta, gamma)
      cv.imshow('frame', res)
      # self.__vw.write(bg)
      cv.waitKey(self.__wait)  

  # 图片停留时间
  def __waitTime(self, img, waitFrame=20):
    for i in range(0, waitFrame):
      cv.imshow('frame', img)
      # self.__vw.write(img)
      cv.waitKey(self.__wait)  